package indirectobject

import (
	"github.com/pkg/errors"
	"strconv"
	"yizhuoyan/go-study/pdfgo/handyio"
	"yizhuoyan/go-study/pdfgo/raw/objects"
	"yizhuoyan/go-study/pdfgo/raw/objects/basicobject"
	"yizhuoyan/go-study/pdfgo/raw/objects/streamobject"
)

var startObjKeywordBytes = []byte("obj")
var endObjKeywordBytes = []byte("endobj")

type IndirectObject struct {
	ObjectNumber        int
	ObjectVersionNumber int
	Object              objects.Object
}

func (this *IndirectObject) MustGetDictionary() *basicobject.Dictionary {
	if rst, is := this.Object.(*basicobject.Dictionary); is {
		return rst
	}
	panic(errors.Errorf("IndirectObject对象非Dictionary"))
}
func (this *IndirectObject) MustGetStreamObject() streamobject.StreamObject {
	if rst, is := this.Object.(streamobject.StreamObject); is {
		return rst
	}
	panic(errors.Errorf("IndirectObject对象非StreamObject"))
}

func (this *IndirectObject) Serialize(w handyio.PdfRawWriter) error {
	w.WriteInt64(int64(this.ObjectNumber))
	w.WriteByte(' ')
	w.WriteInt64(int64(this.ObjectVersionNumber))
	w.WriteByte(' ')
	w.WriteBytes(startObjKeywordBytes)
	w.WriteEndOfLine()
	if err := this.Object.Serialize(w); err != nil {
		return err
	}
	w.WriteEndOfLine()
	w.WriteBytes(endObjKeywordBytes)
	w.WriteEndOfLine()
	return nil

}

func (this *IndirectObject) UnSerialize(r handyio.PdfRawReader) (e error) {
	startAt := r.IndexCurrent()
	r.SkipNextWhiteSpaces()
	onBytes := r.NextBytesUntilWhiteSpace()
	if len(onBytes) == 0 {
		return r.NotSupport("无obj-num")
	}
	onValue, err := strconv.ParseInt(string(onBytes), 10, 64)
	if err != nil {
		_ = r.IndexMoveTo(startAt)
		return err
	}
	this.ObjectNumber = int(onValue)
	r.SkipNextWhiteSpaces()
	gnBytes := r.NextBytesUntilWhiteSpace()
	if len(gnBytes) == 0 {
		_ = r.IndexMoveTo(startAt)
		return r.NotSupport("无generate-number")
	}
	gnValue, err := strconv.ParseInt(string(gnBytes), 10, 64)
	if err != nil {
		_ = r.IndexMoveTo(startAt)
		return err
	}
	this.ObjectVersionNumber = int(gnValue)
	r.SkipNextWhiteSpaces()
	if !r.NextBytesEquals(startObjKeywordBytes) {
		_ = r.IndexMoveTo(startAt)
		return r.NotSupport("无startObj")
	}
	r.SkipNextWhiteSpaces()
	if this.Object, err = readObject(r); err != nil {
		_ = r.IndexMoveTo(startAt)
		return errors.Wrapf(err, "读取对象%v %v", this.ObjectNumber, this.ObjectVersionNumber)
	}
	r.SkipNextWhiteSpaces()
	if !r.NextBytesEquals(endObjKeywordBytes) {
		_ = r.IndexMoveTo(startAt)
		return r.NotSupport("无endObj")
	}
	r.SkipNextWhiteSpaces()
	return nil
}
func readObject(r handyio.PdfRawReader) (objects.Object, error) {
	//try com
	basicObject, err := basicobject.ReadrBasicObject(r)
	if err == nil {
		if dictionary, is := basicObject.(*basicobject.Dictionary); is {
			//try stream object
			startAt := r.IndexCurrent()
			if r.NextBytesEquals(streamobject.StartStreamKeywordBytes) {
				_ = r.IndexMoveTo(startAt)
				streamObj, err := streamobject.ReadStream(dictionary, r)
				if err != nil {
					return nil, err
				}
				return streamObj, nil
			}
		}
		return basicObject, nil
	}
	return nil, err
}
